package com.mhd.usercontroller.service.impl;


import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.digest.DigestUtil;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mhd.usercontroller.dao.UserDao;
import com.mhd.usercontroller.entity.User;
import com.mhd.usercontroller.ex.UserException;
import com.mhd.usercontroller.service.UserService;
import com.mhd.usercontroller.vo.TableVo;
import com.mhd.usercontroller.vo.UserRegistVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;


@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    UserDao userDao;

    // 处理文件上传路径，使用依赖注入从propeties文件中获取配置
    @Value("${file.upload.path}")
    String fileUploadPath;


    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public User getUser(Integer id) {
        return userDao.getUserById(id);
    }


    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public User login(String username, String password) {

        //1. 根据用户名查询用户信息
        User user =  userDao.getUserByName(username);

        if (user == null){  // 没用匹配的用户，直接返回null
            return null;
        }else {
            //2. 比对密码是否正确
            final String dbpassword = user.getPassword();

            // 转换 password 为 md5 字符串
            final String md5password = DigestUtil.md5Hex(password);

            if (dbpassword.equals(md5password)){
                return user;
            }

            return null;
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void registUser(UserRegistVo userRegistVo) throws Exception {

        //0 检查当前用户名是否存在
        final String username = userRegistVo.getUsername();
        final User dbuser = userDao.getUserByName(username);
        if (dbuser!=null){
            // 用户名重复了
            throw new UserException(-1001,"用户名重复了");
        }


        //1. 保存文件到指定目录
        final MultipartFile photo = userRegistVo.getPhoto();

        // 生成一个唯一的文件名
        final String prefix = UUID.randomUUID().toString();
        final String fileName = prefix + "_" + photo.getOriginalFilename();

        final String finalFilePath = fileUploadPath + fileName;

        photo.transferTo(new File(finalFilePath));

        log.debug("上传头像成功,finalFilePath={}",finalFilePath);

        //2. 把用户的数据写入数据库表
        final User user = new User();

        user.setName(userRegistVo.getUsername());
        final String password = userRegistVo.getPassword();
        // password --->  md5
        final String md5Password = DigestUtil.md5Hex(password);
        user.setPassword(md5Password);

        user.setSex(userRegistVo.getSex());
        user.setBirthday(userRegistVo.getDate());

        user.setRegistTime(new Date());
        user.setPhotopath(fileName);

        userDao.insertUser(user);
        log.debug("用户数据落库成功,user={}",user);


    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public TableVo<User> getUserByPage(Integer page, Integer limit) {

        // 查询总条数
        Integer count = userDao.getTotalCount();

        // 查询当前页的数据
        // 把当前页号转换成 mysql 分页查询的起始行号
        int start = (page-1)*limit;

        List<User> data =  userDao.getUserByPage(start,limit);

        final TableVo tableVo = TableVo.ok(count, data);

        return tableVo;
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addUser(User user) throws UserException {

        //1. 判断用户名是否存在
        final String uname = user.getName();
        final User dbuser = userDao.getUserByName(uname);
        if (dbuser!=null){
            throw new UserException(-1001,"用户名重复");
        }
        //2. 密码处理
        final String md5Password = DigestUtil.md5Hex(user.getPassword());
        user.setPassword(md5Password);

        //3. 落库
        userDao.insertUser(user);


    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delUserByIds(String[] ids) {

        userDao.deleteUserByIds(ids);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUserById(User user) throws UserException {

        //1. 判断user中是否有id
        final Integer id = user.getId();
        if (id == null){
            throw new UserException(-1002,"修改用户没传id");
        }

        // 判断密码是否被修改了
        final String password = user.getPassword();
        final User dbuser = userDao.getUserById(id);
        final String dbpassword = dbuser.getPassword();

        if (!dbpassword.equals(password)){
            final String md5Pass = DigestUtil.md5Hex(password);
            if (md5Pass.equals(dbpassword)){
                // 没改密码
                throw new UserException(-1003,"密码跟原密码一致");
            }else {  // 写了新的密码跟原理的md5不一致了
                user.setPassword(md5Pass);
            }
        }

        //2. 更新用户数据
        userDao.updateUserById(user);

    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public TableVo<User> getAllUsersByPageHelper(Integer page, Integer limit, String username, String sex, Date birthday) {

        final User userCondition = new User();
        userCondition.setName(username);
        userCondition.setSex(sex);
        userCondition.setBirthday(birthday);

        PageHelper.startPage(page,limit); // 设置分页插件查询的页号和页大小
        List<User> data = userDao.getAllUsersByCondition(userCondition);

        final PageInfo<User> pageInfo = new PageInfo<>(data);
        final long total = pageInfo.getTotal();

        return TableVo.ok((int) total,data);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public String export() {

        //1. 查询用户表的所有数据 ，生成一个list
        final List<User> allUsers = userDao.getAllUsers();

        final String filename = UUID.randomUUID().toString()+".csv";

        final String finalFilePath = fileUploadPath + filename;  // 得到最终csv文件的物理路径

        //2. 把list 写入一个csv文件中
        CsvWriter writer = CsvUtil.getWriter(finalFilePath, CharsetUtil.CHARSET_UTF_8);

        //3. 返回生成的csv文件名
        writer.writeBeans(allUsers);

        return filename;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importUsers(MultipartFile file) throws IOException {

        // 1. 接收csv文件

        final String filename = UUID.randomUUID().toString()+".csv";

        final String finalFilepath = fileUploadPath + filename;

        file.transferTo(new File(finalFilepath));

        // 2. 读取csv文件中的内容，转换为 List<User>

        final CsvReader reader = CsvUtil.getReader();
        //假设csv文件在classpath目录下
        final List<User> userList = reader.read(
                ResourceUtil.getUtf8Reader(finalFilepath), User.class);

        // 3. 批量插入user数据
        userDao.insertUserList(userList);

    }
}
